﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Deployment.BuildManager.ExternalProcess.Common;
using Deployment.TeamFoundation.Entity;
using Deployment.TeamFoundation.Logic;
using Deployment.Manager.Configuration;
using Deployment.Manager.Configuration.Enum;
using System.Threading;

namespace Deployment.BuildManager.ExternalProcess.GetSource
{
    public class BuildTask : IBuildTask
    {
        #region IBuildTask Members

        public SetupInfo Execute(SetupInfo info)
        {
            this.GetBranchType(info);
            //this.GetVersion(info);

            //Limpa o diretorio temporario
            this.ClearDownloadFolder(info.DownloadPath);

            //Download dos compilados.
            this.SendMessage("Baixando os Arquivos Compilados...");
            GetFilesFromUri(info.CompiledUri + Path.DirectorySeparatorChar + BuildConstants.CompiledFolder, info.CompiledPath, TFSGetType.Folder);

            if (!Directory.Exists(info.CompiledPath + Path.DirectorySeparatorChar + info.ProductName))
            {
                throw new Exception("Branch inválido");
            }

            //Download do Projeto de Setup Template.
            this.SendMessage("Baixando Projeto de Template...");
            GetFilesFromUri(info.TemplateProjectUri, info.SetupTemplateProjectPath, TFSGetType.Folder);

            //Se vier uma URI faz download
            //Senão copia de uma pasta local.
            if (info.SetupUri.StartsWith("$"))
            {
                this.SendMessage("Baixando os Arquivos do Setup...");
                GetFilesFromUri(string.Concat(info.SetupUri, "/x86/", BuildConstants.SetupXmlConfigFileName), info.SetupPath, TFSGetType.File);
                //GetFilesFromUri(string.Concat(info.SetupUri, "/x86/", BuildConstants.SetupBinFolder), string.Concat(info.SetupPath, "\\", BuildConstants.SetupBinFolder), TFSGetType.Folder);
            }
            //else
            //{
            //    this.SendMessage("Copiando os Arquivos do Setup...");
            //    GetFilesFromFolder(string.Concat(info.SetupUri, "\\x86\\", BuildConstants.SetupBinFolder), string.Concat(info.SetupPath, "\\", BuildConstants.SetupBinFolder));
            //    GetFileFromFolder(string.Concat(info.SetupUri, "\\x86\\", BuildConstants.SetupXmlConfigFileName), info.SetupPath + Path.DirectorySeparatorChar + BuildConstants.SetupXmlConfigFileName);
            //}

            //Remove o read-only de todos os arquivos do projeto template.
            FileHelper.ClearAttributes(info.DownloadPath);

            return info;
        }

        public void Cancel()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region Private [ Methods ]

        private void GetFilesFromUri(string SourceUri, string downloadPath, TFSGetType getType)
        {
            SourceControl.Instance.GetSource("DeploymentPackager", SourceUri, downloadPath, true, getType);
        }

        private void GetFilesFromFolder(string sourceFolder, string destinationPath)
        {
            if (!Directory.Exists(sourceFolder))
            {
                throw new Exception(String.Format("O diretório {0} não existe!", sourceFolder));
            }

            if (!Directory.Exists(destinationPath))
            {
                Directory.CreateDirectory(destinationPath);
                copyDirectory(sourceFolder, destinationPath);
            }
        }

        private void GetFileFromFolder(string sourceFilePath, string destinationFilePath)
        {
            try
            {
                File.Copy(sourceFilePath, destinationFilePath, true);
            }
            catch (Exception ex)
            {
                throw new Exception(String.Format("Não foi possivel copiar o arquivo {0}!", sourceFilePath));
            }
        }

        public static void copyDirectory(string source, string destination)
        {
            String[] Files;

            if (destination[destination.Length - 1] != Path.DirectorySeparatorChar)
                destination += Path.DirectorySeparatorChar;

            if (!Directory.Exists(destination)) Directory.CreateDirectory(destination);

            Files = Directory.GetFileSystemEntries(source);

            foreach (string Element in Files)
            {
                if (Directory.Exists(Element))
                    copyDirectory(Element, destination + Path.GetFileName(Element));
                else
                    File.Copy(Element, destination + Path.GetFileName(Element), true);
            }
        }

        private void ClearDownloadFolder(string downloadPath)
        {
            this.SendMessage("Limpando Diretório Temporário...");

            if (!Directory.Exists(downloadPath))
                Directory.CreateDirectory(downloadPath);
            else
            {
                FileHelper.ClearAttributes(downloadPath);
                Directory.Delete(downloadPath, true);
                Directory.CreateDirectory(downloadPath);
            }
        }

        private void GetBranchType(SetupInfo info)
        {
            if (info.CompiledUri.Split('/').GetValue(2).ToString().Equals("HotFix", StringComparison.OrdinalIgnoreCase))
                info.BranchType = Deployment.Manager.Configuration.Enum.BranchType.HotFix;
            else if (info.CompiledUri.Split('/').GetValue(2).ToString().Equals("ServicePack", StringComparison.OrdinalIgnoreCase))
                info.BranchType = Deployment.Manager.Configuration.Enum.BranchType.ServicePack;
            else
                throw new Exception("Invalid Branch Type.");
        }

        public void GetVersion(SetupInfo info)
        {
            string strVersion = info.CompiledUri.Split('/').GetValue(4).ToString();
            info.Version = new PSE.Framework.Common.Version(strVersion);
        }

        #endregion Private [ Methods ]

        #region [ Events ]

        public event EventHandler<MessageEventArgs> MessageReceived;

        private void SendMessage(string message)
        {
            if (MessageReceived != null)
            {
                MessageEventArgs eventArgs = new MessageEventArgs(message);
                Logger.Log(message, Logger.EntryType.Information);
                MessageReceived(this, eventArgs);
            }
        }

        #endregion [ Events ]
    }
}
